﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace SwimmingCompetitions
{
    /// <summary>
    /// Form for choosing participant.
    /// </summary>
    public partial class AutosuggestForm : Form
    {
        private readonly List<string> _items;

        /// <summary>
        /// Fired when choice is confirmed. Chosen item is passed.
        /// </summary>
        public event Action<string> ItemChosen;

        public AutosuggestForm()
        {
            InitializeComponent();
        }

        public AutosuggestForm(List<string> items)
            : this()
        {
            _items = items;
            _listBoxItems.Items.AddRange(_items.ToArray());
        }

        private void updateSuggestedItems(string token)
        {
            _listBoxItems.SuspendLayout();
            _listBoxItems.Items.Clear();
            _listBoxItems.Items.AddRange(
                string.IsNullOrEmpty(token)
                    ? _items.ToArray()
                    : _items.Where(item => item.StartsWith(token, StringComparison.OrdinalIgnoreCase)).ToArray());
            if (_listBoxItems.Items.Count == 1)
            {
                _listBoxItems.SelectedIndex = 0;
            }
            _listBoxItems.ResumeLayout();
            _buttonOk.Enabled = _listBoxItems.SelectedIndex >= 0;
        }

        private void textBoxSearchTextChanged(object sender, EventArgs e)
        {
            _buttonAdd.Enabled = _textBoxSearch.Text.Length > 0;
            updateSuggestedItems(_textBoxSearch.Text);
        }

        private void buttonAddClick(object sender, EventArgs e)
        {
            var newItem = _textBoxSearch.Text;
            if (!_items.Select(item => item.ToUpper()).Contains(newItem.ToUpper()))
            {
                _items.Add(newItem);
                _listBoxItems.Items.Add(newItem);
                updateSuggestedItems(newItem);
            }
        }

        private void buttonOkClick(object sender, EventArgs e)
        {
            if (ItemChosen != null) ItemChosen(_listBoxItems.SelectedItem.ToString());
            DialogResult = DialogResult.OK;
        }

        private void buttonCancelClick(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        private void listBoxParticipantsSelectedIndexChanged(object sender, EventArgs e)
        {
            _buttonOk.Enabled = _listBoxItems.SelectedIndex >= 0;
        }

        private void listBoxParticipantsDoubleClick(object sender, EventArgs e)
        {
            if (_buttonOk.Enabled) buttonOkClick(sender, e);
        }

        private void formLoad(object sender, EventArgs e)
        {
            updateSuggestedItems(string.Empty);
            _textBoxSearch.Focus();
        }

        /// <summary>
        /// Highlights autosuggest items.
        /// </summary>
        private void listBoxParticipantsDrawItem(object sender, DrawItemEventArgs e)
        {
            var token = _textBoxSearch.Text;
            var item = _listBoxItems.Items[e.Index];
            var brush = e.State.HasFlag(DrawItemState.Selected)
                            ? Brushes.Coral //Brushes.Orange
                            : Brushes.White;
            e.Graphics.FillRectangle(brush, e.Bounds);

            var text = item.ToString();
            using (var bold = new Font(Font.FontFamily, Font.SizeInPoints, FontStyle.Bold | Font.Style, Font.Unit))
            {
                if (text.StartsWith(token, StringComparison.OrdinalIgnoreCase))
                {
                    var start = text.Substring(0, token.Length);
                    e.Graphics.DrawString(start, bold, Brushes.Black, e.Bounds);
                    var size = e.Graphics.MeasureString(start, bold);
                    var newBounds = new Rectangle(e.Bounds.X + (int) size.Width, e.Bounds.Y, e.Bounds.Width,
                                                  e.Bounds.Height);
                    e.Graphics.DrawString(text.Substring(token.Length), Font, Brushes.Black, newBounds);
                }
                else
                {
                    e.Graphics.DrawString(text, Font, Brushes.Black, e.Bounds);
                }
            }
        }
    }
}
